#include "common.h"

#include <assert.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "tests/common_test.h"
#include "src/util/str.h"

/*
演示四个常见的预定义宏的用法

本文件不能改名，不能随意调整各行的顺序，添加或删除行！！！
因为在测试各个预定义宏的功能
*/

static void test___FILE__(void){
    TEST_START_INFO;
    TEST_LINE_REPORT_START;

    printf("%s\n", __FILE__);

    // 本文件的文件名
    char *file_name = "test_FILE_.c";

    // __FILE__ 宏获取的文件所在的相对路径
    char *original_name = strdup(__FILE__);
    
    // 解析出来的文件名
    char *maybe_name = original_name + strlen(__FILE__) - strlen(file_name);

    printf("%s\n", maybe_name);

    assert(!strcmp(maybe_name,file_name));
    free(original_name);
    TEST_END_INFO;
}

static void test___DATE__(void){
    /* 
    __DATE__    当前日期，一个以 “MMM DD YYYY” 格式表示的字符串常量。
    月份数据是英文字符串
    */
    char *date = __DATE__ ;
    char MON[4];
    char month;
    long dd;
    long year;
    char tmp[5];
    bool result;
    static const char *static_month_buf[] = {
        "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};

    // 处理月份
    memcpy(tmp, date, 3);
    tmp[3] = '\0';

    for(int i = 0;i< 12;++i){
        if (0 == strcmp(static_month_buf[i],tmp)){
            month=i;
            break;
        }
    }

    memcpy(MON,tmp,4);
    // 打印月份
    printf("%s\n",MON);

    // 处理日,往后跨4个字符，见预定义宏的日期格式
    date += 4;
    
    // 如果不用这种方式解析，直接用date，里面可能是有两个数字，“日 年”
    memcpy(tmp, date, 2);
    tmp[2] = '\0';
    
    result = sc_str_parse_integer(tmp, &dd);
    assert(result);
    assert(dd > 0);

    // 处理年，再往后跨3个字符
    date += 3;
    result = sc_str_parse_integer(date, &year);
    assert(result);
    // 2024年写的这个测试，如果在这之前，应该是穿越了
    assert(year > 2023);

    // 打印的结果看日志
    printf("%s\n", date);
}

static void test___FUNCTION__(void){
    // 下面的 __func__ 两个宏是不能直接赋值给变量的
    char *fun_name = strdup(__FUNCTION__);
    char *fun_name2 = strdup(__func__);

    assert(!strcmp(fun_name2, fun_name));
    assert(!strcmp(fun_name,"test___FUNCTION__"));

    free(fun_name);
    free(fun_name2);
}

static void test___TIME__(void){
    /*
    __TIME__    当前时间，一个以 “HH:MM:SS” 格式表示的字符串常量。
    __TIME__ 宏指令包含程序编译的时间

    TODO 某些情况下，下面的代码会出问题，sc_str_parse_integers 方法执行的结果是0,到底是什么原因？ __TIME__ 
    https://www.cnblogs.com/agpro/archive/2010/06/24/1764448.html
    */

    char *time = __TIME__;
    printf("__TIME__: %s\n",time);

    long out[3] ={0,0,0};
    size_t count = sc_str_parse_integers(time, ':', 3, out);
    printf("sc_str_parse_integers 解析的结果-count: %ld\n",count);
    printf("sc_str_parse_integers 解析的结果-out[0]: %ld\n",out[0]);
    printf("sc_str_parse_integers 解析的结果-out[1]: %ld\n",out[1]);
    printf("sc_str_parse_integers 解析的结果-out[2]: %ld\n",out[2]);

    // 不立即输出有可能在出错时，打印不到meson生成的日志文件中！
    fflush(stdout);

    assert(3 == count);

    assert(out[0] >= 0 && out[0] <= 23);
    assert(out[0] >= 0 && out[0] <= 59);
    assert(out[0] >= 0 && out[0] <= 59);
}

static void test___LINE__(void){
    uint first_line = __LINE__;
    uint second_line = __LINE__;

    assert(first_line + 1 == second_line);

    // 强制修改行号 , 添加了这个宏定义，在vscode中加断点就出问题了，会找不到对应的行
    #line 300
    first_line = __LINE__;
    second_line = __LINE__;
    assert(first_line  == 300);
    assert(first_line + 1 == second_line);
    printf("%d\n",first_line);

}

int main(int argc, char *argv[]) {
    (void) argc;
    (void) argv;

    test___FILE__();
    test___DATE__();
    test___FUNCTION__();
    test___TIME__();
    test___LINE__();

    return 0;
};